package com.linln.admin.system.controller;


import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.linln.admin.system.service.AppService;
import com.linln.common.data.QuerySpec;
import com.linln.common.utils.*;
import com.linln.component.actionLog.annotation.EntityParam;
import com.linln.component.shiro.ShiroUtil;
import com.linln.modules.system.domain.*;
import com.linln.modules.system.repository.CompanyRepository;
import com.linln.modules.system.repository.DepRepository;
import com.linln.modules.system.repository.RoleRepository;
import com.linln.modules.system.repository.UserRepository;
import com.linln.modules.system.service.RoleService;
import com.linln.modules.system.service.UserService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author 小懒虫
 * @date 2018/8/14
 */
@Controller
@RequestMapping("/system/user")
public class UserController {

    @Value("${hostInfo.middle}")
    private String middle;
    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private ThymeleafViewResolver thymeleafViewResolver;

    @Autowired
    private AppService appService;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RoleRepository roleRepository;

    @PersistenceContext
    private EntityManager entityManager;
    @Autowired
    private DepRepository depRepository;
    @Autowired
    private CompanyRepository companyRepository;

    /**
     * 列表页面
     */
    @GetMapping("/index")
    @RequiresPermissions("system:user:index")
    public ResponseEntity<?> index(Model model, User user) {

        return appService.layTable(userRepository, before -> {
                    // 添加模板变量
                    model.addAttribute("type", HttpServletUtil.getParameter("type",""));
                    model.addAttribute("companyId", HttpServletUtil.getParameter("companyId",""));

                    return model;
                },

                after -> {

                    QuerySpec querySpec = QuerySpec.matching()
                            .withMatcher("nickname", QuerySpec.LIKE)
                            .withMatcher("type", QuerySpec.EQUAL)
                            .withMatcher("companyId", QuerySpec.EQUAL);
                    return QuerySpec.of(querySpec);

                },

                "/system/user/index",

                (pageResult) -> {
                    // 在这里处理 pageResult
                    // 例如：修改每一条数据
                    pageResult.getContent().forEach(item -> {
                        // 对每一项数据进行处理
                        // (User) item;
                    });
                }

        );

    }


    /**
     * 跳转到添加页面
     */
    @RequestMapping("/form")
    @RequiresPermissions("system:user:form")
    public ResponseEntity<?> form(Model model, @EntityParam User user) throws Exception {

        return appService.form(userRepository, "/system/user/form", (isEdit) -> {

            // 获取所有角色
            String type = HttpServletUtil.getParameter("type", "-1");
            QuerySpec querySpec = QuerySpec.matching();
            if(!type.equals("-1")){
                querySpec.withMatcherValue("type", QuerySpec.EQUAL,type);
            }
            Specification<Role> spec = QuerySpec.of(querySpec);
            List<Role> roles = roleRepository.findAll(spec);

            model.addAttribute("roles", roles);
            model.addAttribute("type", HttpServletUtil.getParameter("type", "-1"));
            model.addAttribute("companyId", HttpServletUtil.getParameter("companyId", ""));
            List<Dep> deps = depRepository.findAll();
            model.addAttribute("deps", deps);
            // 获取当前用户的角色
            Set<Role> auths = Collections.emptySet();
            if (isEdit) auths = roleRepository.findByUsers_IdAndStatus(user.getId(), (byte) 1);
            model.addAttribute("auths", auths);

            return model;

        }, (data) -> {

//            try {
//                String json               = HttpServletUtil.getRequest().getReader().lines().collect(Collectors.joining(System.lineSeparator()));
//                ObjectMapper objectMapper = new ObjectMapper();
//                Map<String, Object> map   = objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {});
//            } catch (IOException e) {
//                throw new RuntimeException(e);
//            }
//            email.matches("^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$"),

            // 保存前数据校验
            List<ValidationUtil.ValidationRule<?>> rules = new ArrayList<>();

            rules.add(new ValidationUtil.ValidationRule<>(
                    user.getUsername(),
                    username -> username != null && !username.isEmpty(),
                    "请输入登录账号"
            ));

            rules.add(new ValidationUtil.ValidationRule<>(
                    user.getNickname(),
                    nickname -> nickname != null && !nickname.isEmpty(),
                    "请输入用户昵称"
            ));
            if(user.getType().equals("1")){
                rules.add(new ValidationUtil.ValidationRule<>(
                        user.getDepId(),
                        depId -> depId != null && !depId.equals(0L),
                        "请选择所属科室"
                ));
            }

            // 执行校验
            return ValidationUtil.validateFields(rules);

        }, (data) -> {

            if (user.getId() != null) { // 编辑
                User beUser = userRepository.getById(user.getId());
               // EntityBeanUtil.copyProperties(beUser, user); // 将beMenu 字段复制到 menu
                user.setPassword(beUser.getPassword());
                user.setCreateDate(beUser.getCreateDate());
                user.setSalt(beUser.getSalt());
            }

            // 设置角色信息
            String[] roleIds = HttpServletUtil.getParameterValues("roleId[]");
            if (roleIds != null) {
                HashSet<Role> roles = new HashSet<>();
                for (String roleId : roleIds) {
                    roles.add(roleRepository.getById(Long.valueOf(roleId)));
                }
                user.setRoles(roles);
            }

            if(user.getType().equals("1") && user.getDepId()!=null){
                QuerySpec querySpec = QuerySpec.matching().withMatcherValue("deptId", QuerySpec.EQUAL,user.getDepId());
                 List<Dep> deps = depRepository.findAll(QuerySpec.of(querySpec));
                user.setDepName(deps.get(0).getName());
            }
            if(user.getType().equals("2") && user.getCompanyId()!=null){
                user.setCompanyName(companyRepository.getById(user.getCompanyId()).getName());
            }

            // 数据处理
            return user;
        },

        (data) -> {
            // 保存后续逻辑在这写
        });
    }


    /**
     * 修改状态
     * @param model
     * @param user
     * @return
     * @throws Exception
     */
    @RequestMapping("/state")
    @RequiresPermissions("system:user:state")
    public ResponseEntity<?> state(Model model, @EntityParam User user) throws Exception {

        return appService.save(userRepository, (data) -> {

            // 校验数据
            return ValidationUtil.validateFields(new ArrayList<>());

        }, (data) -> {

//            try {
//                throw new Exception("异常");
//            }

            // 处理数据
            User origin = userRepository.getById(user.getId());
            origin.setStatus(user.getStatus());
            return origin;

        }, (data) -> {
            // 更新后操作
        });

    }


    /**
     * 跳转到授权页面
     */
    @RequestMapping("/pwd")
    @RequiresPermissions("system:user:pwd")
    public ResponseEntity<?> pwd(Model model,
                                  @RequestParam(value = "id") User user,
                                  @RequestParam(required = false) String password,
                                  @RequestParam(required = false) String confirm) throws Exception {

        return appService.form(userRepository, "/system/user/pwd", (isEdit) -> {

            return model;

        }, (data) -> {

            // 保存前数据校验
            List<ValidationUtil.ValidationRule<?>> rules = new ArrayList<>();

            rules.add(new ValidationUtil.ValidationRule<>(
                    password,
                    passwordPram -> passwordPram != null && !passwordPram.isEmpty(),
                    "请输入密码"
            ));

            rules.add(new ValidationUtil.ValidationRule<>(
                    confirm,
                    confirmPram -> confirmPram != null && !confirmPram.isEmpty(),
                    "请再次输入密码"
            ));
            // 新增密码复杂度校验（至少包含大小写字母、数字、特殊字符）
            rules.add(new ValidationUtil.ValidationRule<>(
                    password,
                    pwd -> pwd != null && pwd.matches("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[\\W_]).+$"),
                    "密码必须包含大小写字母、数字和特殊符号"
            ));
            rules.add(new ValidationUtil.ValidationRule<>(
                    password,
                    passwordPram -> Objects.equals(passwordPram, confirm),
                    "两次密码输入不一致"
            ));

            // 执行校验
            return ValidationUtil.validateFields(rules);

        }, (data) -> {

            // 数据处理

            String salt = ShiroUtil.getRandomSalt();
            String encrypt = ShiroUtil.encrypt(password, salt);
            user.setPassword(encrypt);
            user.setSalt(salt);

            return user;

        },

        (data) -> {
            // 保存后续逻辑在这写
        });
    }

    //从中台系统同步用户
    @RequestMapping("/syncUser")
    @RequiresPermissions("system:user:form")
    public ResponseEntity<?> syncUser(Model model, User user, HttpServletRequest request) {
        String serverName = request.getServerName();
        String url = "http://"+serverName+":"+middle;
        //发起网络请求
        try {
            // 1. 发起网络请求获取用户数据
            String apiUrl = url+"/api/sys/user";
            String Authorization ="Fv340FP60umod0YctyaFRsFfxLy3eMTA";
            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", Authorization);
            HttpEntity<String> requestEntity = new HttpEntity<>(headers);
            ResponseEntity<String> response = new RestTemplate().exchange(
                    apiUrl,
                    HttpMethod.GET,
                    requestEntity,
                    String.class
            );

            // 2. 解析响应数据
            if (response.getStatusCode().is2xxSuccessful()) {
                ObjectMapper mapper = new ObjectMapper();
                // 先将响应体解析为一个 Map
                Map<String, Object> responseMap = mapper.readValue(response.getBody(), new TypeReference<Map<String, Object>>(){});

                // 从 Map 中获取 "data" 字段，该字段是一个 List
                @SuppressWarnings("unchecked")
                List<Map<String, Object>> data = (List<Map<String, Object>>) responseMap.get("data");
                // 将 "data" 字段解析为 List<MiddleUser>
                JavaType javaType = mapper.getTypeFactory().constructCollectionType(List.class, MiddleUser.class);
                List<MiddleUser> remoteUsers = mapper.convertValue(data, javaType);

               // List<MiddleUser> remoteUsers = mapper.readValue(response.getBody(), new TypeReference<List<MiddleUser>>(){});

                // 3. 同步到本地数据库
                remoteUsers.forEach(remoteUser -> {
                    // 检查用户是否已存在
                    User localUser = userRepository.findByUsername(remoteUser.getUsername());
                    if (localUser == null) {
                        localUser = new User();
                        localUser.setMiddleUserId(remoteUser.getId());
                        localUser.setUsername(remoteUser.getUsername());
                        localUser.setPassword(remoteUser.getPassword());
                        localUser.setSalt(remoteUser.getSalt());
                        localUser.setNickname(remoteUser.getNickname());
                        localUser.setPicture(remoteUser.getPicture());
                        localUser.setSex(remoteUser.getSex());
                        localUser.setPhone(remoteUser.getPhone());
                        localUser.setEmail(remoteUser.getEmail());
                        localUser.setCreateDate(new Date());
                        localUser.setUpdateDate(new Date());
                        localUser.setType("-1");
                        localUser.setStatus((byte) 1);
                        userRepository.save(localUser);
                    }else{
                        localUser.setMiddleUserId(remoteUser.getId());
                        userRepository.save(localUser);
                    }
                });

                return ResponseEntity.ok(ResultVoUtil.success("同步成功"));
            }
            return ResponseEntity.ok(ResultVoUtil.error("远程服务响应异常"));
        } catch (IOException e) {
            return ResponseEntity.ok(ResultVoUtil.error("数据解析失败：" + e.getMessage()));
        } catch (Exception e) {
            return ResponseEntity.ok(ResultVoUtil.error("同步失败：" + e.getMessage()));
        }
    }





}
